/**
 * Copyright (C) 2009 alex <me@alex.0x08.org>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package uber.netbsd.community.action;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontValidate;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.LocalizableMessage;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.Wizard;
import uber.netbsd.community.dao.Person;
import uber.netbsd.community.dao.PersonManager;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;
import net.sourceforge.stripes.action.UrlBinding;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.support.WebApplicationContextUtils;
import uber.netbsd.community.dao.Role;

/**
 * ActionBean that handles the registration of new users.
 *
 * @author Tim Fennell
 */
@UrlBinding("/action/Register")
@Wizard
public class RegisterActionBean extends BaseActionBean {

    @ValidateNestedProperties({
        @Validate(field = "username", required = true, minlength = 5, maxlength = 20),
        @Validate(field = "password", required = true, minlength = 5, maxlength = 20),
        @Validate(field = "firstName", required = true, maxlength = 50),
        @Validate(field = "lastName", required = true, maxlength = 50)
    })
    private Person user;
    @Validate(required = true, minlength = 5, maxlength = 20, expression = "this == user.password")
    private String confirmPassword;

   

    /** The user being registered. */
    public void setUser(Person user) {
        this.user = user;
    }

    /** The user being registered. */
    public Person getUser() {
        return user;
    }

    /** The 2nd/confirmation password entered by the user. */
    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    /** The 2nd/confirmation password entered by the user. */
    public String getConfirmPassword() {
        return confirmPassword;
    }

    /**
     * Validates that the two passwords entered match each other, and that the
     * username entered is not already taken in the system.
     */
    @ValidationMethod
    public void validate(ValidationErrors errors) {
        
        if (PersonManager.getInstance().getPerson(this.user.getUsername()) != null) {
            errors.add("user.username", new LocalizableError("usernameTaken"));
        }
    }

    @HandlesEvent("gotoStep1")
    @DontValidate
    public Resolution goStep1() {

        return new RedirectResolution("/register/stage1");
    }

    @HandlesEvent("Back")
    @DontValidate
    public Resolution goBack() {

        return new RedirectResolution("/");
    }


    public Resolution gotoStep2() throws Exception {
        return new ForwardResolution("/register/stage2");
    }

    /**
     * Registers a new user, logs them in, and redirects them to the bug list page.
     */
    @DefaultHandler
    public Resolution register() {
        PersonManager pm = PersonManager.getInstance();
        this.user.addRole(Role.ROLE_USER);
        pm.saveOrUpdate(this.user);

        /**
         * это блять высший пилотаж: programmatic auth в spring security. \m/ \m/
         */
        try {
            Authentication request = new UsernamePasswordAuthenticationToken(
                    this.user.getUsername(), this.user.getPassword());
            ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getContext().getServletContext());


            AuthenticationManager am = (AuthenticationManager) context.getBean("bz-auth-manager");

            Authentication result = am.authenticate(request);
            SecurityContextHolder.getContext().setAuthentication(result);

        } catch (AuthenticationException e) {
            getContext().getMessages().add(new LocalizableMessage(e.getLocalizedMessage()));
            return new RedirectResolution("/index.jsp");
        }

        getContext().getMessages().add(
                new LocalizableMessage(getClass().getName() + ".successMessage",
                this.user.getFirstName(),
                this.user.getUsername()));

        return new RedirectResolution("/index.jsp");
    }
}
